package com.example.demo.database.services.mysql;

import com.example.demo.database.services.base.SqlCompiler;
import com.example.demo.database.services.base.SqlGenerator;

import java.util.ArrayList;
import java.util.List;

public class MySqlCompiler implements SqlCompiler {

    private static MySqlCompiler mySqlCompiler = null;

    public static MySqlCompiler getInstance() {
        if (mySqlCompiler == null) {
            mySqlCompiler = new MySqlCompiler();
        }
        return mySqlCompiler;
    }

    /**
     * 创建表
     *
     * @param tableName
     * @param generator
     */
    public String create(String tableName, SqlGenerator generator) {
        //创建一个生成器
        ColumnGenerator columnGenerator = new ColumnGenerator();
        //通过生成器返回一个list
        generator.generate(columnGenerator);
        //返回sql
        String sql = createCompile(tableName, columnGenerator.list);
        //执行sql
        MySqlConnector.getInstance().runOne(sql);
        return sql;
    }

    public String dropIfExists(String tableName) {
        String sql = "DROP TABLE IF EXISTS `" + tableName + "` ";
        //执行sql
        MySqlConnector.getInstance().runOne(sql);
        return sql;
    }

    /**
     * 创建语句编译
     *
     * @param tableName
     * @param list
     * @return
     */
    private String createCompile(String tableName, List<Column> list) {
        StringBuffer stringBuffer = new StringBuffer();
        //创建表
        stringBuffer.append("CREATE TABLE `");
        stringBuffer.append(tableName);
        stringBuffer.append("` ( ");
        List<String> primaryList = new ArrayList<>();
        for (Column column : list) {
            //获得编译结果
            stringBuffer.append(column.getCompileString());
            if (column.primaryKey) {
                primaryList.add(column.name);
            }
        }
        if (!primaryList.isEmpty()) {
            //如果主键列表不是空的，那么就执行主键生成指令
            stringBuffer.append(" PRIMARY KEY(");
            for (String name : primaryList) {
                stringBuffer.append("`");
                stringBuffer.append(name);
                stringBuffer.append("`,");
            }
            //删掉最后一个逗号
            stringBuffer.deleteCharAt(stringBuffer.length() - 1);
            stringBuffer.append("),");
        }
        //删掉最后一个逗号
        stringBuffer.deleteCharAt(stringBuffer.length() - 1);

        //创建表结束
        stringBuffer.append(" ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;");
        return stringBuffer.toString();
    }

    public static class ColumnGenerator implements SqlCompiler.ColumnGenerator {

        @Override
        public SqlCompiler.Column integer(String name) {
            Column column = new Column(name, "INTEGER");
            list.add(column);
            return column;
        }

        private List<Column> list = new ArrayList<>();

        /**
         * 用于在数据表中创建一个自增的 UNSIGNED BIGINT 类型（主键）的列
         *
         * @param name
         * @return
         */
        public Column bigIncrements(String name) {
            Column column = new Column(name, "BIGINT UNSIGNED");
            list.add(column);
            column.autoIncrement();
            return column;
        }

        /**
         * 用于在数据表中创建一个自增的 UNSIGNED BIGINT 类型（主键）的列
         *
         * @return
         */
        public Column bigIncrements() {
            return bigIncrements("id");
        }

        /**
         * 用于在数据表中创建一个自增的 UNSIGNED BIGINT 类型（主键）的列
         *
         * @param name
         * @return
         */
        public Column id(String name) {
            return bigIncrements(name);
        }

        /**
         * 用于在数据表中创建一个自增的 UNSIGNED BIGINT 类型（主键）的列
         *
         * @return
         */
        public Column id() {
            return bigIncrements();
        }

        /**
         * 创建一个TIMESTAMP列
         *
         * @param name
         * @return
         */
        public Column timestamp(String name) {
            Column column = new Column(name, "TIMESTAMP");
            list.add(column);
            return column;
        }

        /**
         * 创建创建时间和更新时间列
         */
        public void timestamps() {
            timestamp("created_at").nullable();
            timestamp("updated_at").nullable();
        }

        /**
         * 创建删除时间列
         */
        public void softDeletes() {
            timestamp("deleted_at").nullable();
        }

        /**
         * 创建一个给定长度的 VARCHAR
         *
         * @param name
         * @return
         */
        public Column string(String name, int length) {
            Column column = new Column(name, "VARCHAR(" + length + ")");
            list.add(column);
            return column;
        }

        /**
         * 创建一个给定长度的 VARCHAR
         *
         * @param name
         * @return
         */
        public Column string(String name) {
            return string(name, 255);
        }

        /**
         * 创建一个给定长度的 LONGTEXT
         *
         * @param name
         * @return
         */
        public Column longtext(String name) {
            Column column = new Column(name, "LONGTEXT");
            list.add(column);
            return column;
        }
    }

    public static class Column implements SqlCompiler.Column {
        private String name = null;
        private String type = null;
        private boolean nullable = false;

        private String cDefault = null;

        private String comment = null;

        private boolean autoIncrement = false;

        private boolean primaryKey = false;

        public Column(String name, String type) {
            this.name = name;
            this.type = type;
        }

        /**
         * 设置 INTEGER 类型的列为自动递增 (主键)
         *
         * @return
         */
        public Column autoIncrement() {
            autoIncrement = true;
            primaryKey = true;
            return this;
        }

        /**
         * 允许 NULL 值插入到该列
         */
        public Column nullable() {
            return nullable(true);
        }

        /**
         * 允许 NULL 值插入到该列
         */
        public Column nullable(boolean nullable) {
            this.nullable = nullable;
            return this;
        }

        /**
         * 为该列指定一个「默认值」
         *
         * @param cDefault
         */
        public Column cDefault(String cDefault) {
            this.cDefault = cDefault;
            return this;
        }

        /**
         * 为该列添加注释
         *
         * @param comment
         */
        public Column comment(String comment) {
            this.comment = comment.replace("'", "\\'");
            return this;
        }

        /**
         * 生成编译语句
         *
         * @return
         */
        public String getCompileString() {
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append(" `");
            stringBuffer.append(name);
            stringBuffer.append("` ");
            stringBuffer.append(" ");
            stringBuffer.append(type);
            stringBuffer.append(" ");
            //是否自增主键
            if (autoIncrement) {
                stringBuffer.append("AUTO_INCREMENT ");
            }
            //是否可空
            if (nullable) {
                stringBuffer.append("NULL ");
            } else {
                stringBuffer.append("NOT NULL ");
            }
            //是否有默认值（非空才可以设置默认值）
            if (!nullable && cDefault != null) {
                stringBuffer.append("DEFAULT `");
                stringBuffer.append(cDefault);
                stringBuffer.append("` ");
            }
            if (comment != null) {
                stringBuffer.append("COMMENT '");
                stringBuffer.append(comment);
                stringBuffer.append("' ");
            }
            stringBuffer.append(",");
            return stringBuffer.toString();
        }
    }
}
